﻿using Kendo.Mvc.Extensions;
using Kendo.Mvc.UI;
using OA.Core;
using OA.Models;
using OA.Models.Enums;
using OA.Models.ViewModels;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data.Entity;
using System.Data.Entity.Validation;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Web.Mvc;

namespace OA.Controllers
{
    /// <summary>
    ///  申请单控制器
    /// </summary>
    public class ApplicationFormController : BaseController
    {
        /// <summary>
        ///  申请/备案入口
        /// </summary>
        /// <param name="actionName">ApplyOrEdit : 申请表单, ApplySet : 查看备案</param>
        /// <returns></returns>
        public ViewResult Entrance(string actionName = "Apply")
        {
            ViewBag.ActionName = actionName;

            var viewModel = new List<ApplyEntranceViewModel>();

            var query = Assembly.Load("OA.Models")
                .GetTypes()
                .Where(d => d.BaseType.Name == "ApplicationForm")
                .ToList();

            foreach (var i in query)
            {
                var attr = i.CustomAttributes.SingleOrDefault(d => d.AttributeType.Name == "ApplicationFormTypeAttribute");
                var key = attr.ConstructorArguments.FirstOrDefault().Value.ToString();

                viewModel.Add(new ApplyEntranceViewModel()
                {
                    Name = i.Name,
                    Type = (ApplicationFormType)Enum.Parse(typeof(ApplicationFormType), key),
                });
            }

            var result = viewModel.GroupBy(g => g.Type);

            return View(result);
        }

        /// <summary>
        ///  我的申请记录
        /// </summary>
        /// <returns></returns>
        public ViewResult MyApplication()
        {
            return View();
        }

        /// <summary>
        ///  表单集合
        /// </summary>
        /// <param name="type">表单类型</param>
        /// <returns></returns>
        public ViewResult ApplicationSet(string type)
        {
            return View(type + "Set");
        }
        
        /// <summary>
        ///  表单申请页
        /// </summary>
        /// <param name="type">表单类型</param>
        /// <returns></returns>
        public ViewResult Apply(string type)
        {
            ViewBag.ActionType = "Edit";
            var typeName = Assembly.Load("OA.Models").GetType("OA.Models." + type);
            var db = Context.Set(typeName);

            var entity = (ApplicationForm)db.Create();
            entity.ApplicantId = CurrentUser.UserId;
            entity.Applicant = CurrentUser.Name;
            return View(type, entity);
        }

        /// <summary>
        ///  查看表单详情
        /// </summary>
        /// <param name="type"></param>
        /// <param name="Id"></param>
        /// <returns></returns>
        public ActionResult Detail(string type, string Id)
        {
            var typeName = Assembly.Load("OA.Models").GetType("OA.Models." + type);
            var db = Context.Set(typeName);

            var entity = (ApplicationForm)db.Find(Id);

            if (entity == null)
            {
                // 实例不存在
                return Content("实例不存在!");
            }

            if (entity.CreatorId == CurrentUser.UserId)
            {
                if (entity.Status == ApplicationFormState.未提交)
                {
                    // 必须要未提交的表单才可以编辑
                    ViewBag.ActionType = "Edit";
                }
                else if (entity.Status == ApplicationFormState.申请中)
                {
                    // 可撤回
                    ViewBag.ActionType = "Applying";
                }
                else
                {
                    // 不可操作
                    ViewBag.ActionType = "View";
                }
            }
            else
            {
                // 不可操作
                ViewBag.ActionType = "View";
            }

            return View(type, entity);
        }

        /// <summary>
        ///  审批
        /// </summary>
        /// <returns></returns>
        public ViewResult Approve()
        {
            return View();
        }
        

        /// <summary>
        ///  获取某个表单类型的所有表单
        /// </summary>
        /// <param name="request">请求</param>
        /// <param name="typeName">表单类型, 若没有表单类型, 则获取所有表单</param>
        /// <returns></returns>
        [HttpPost]
        public JsonResult Read([DataSourceRequest] DataSourceRequest request, string typeName)
        {
            if (string.IsNullOrWhiteSpace(typeName))
            {
                var typeSet = Assembly.Load("OA.Models")
                    .GetTypes()
                    .Where(d => d.BaseType.Name == "ApplicationForm");
                
                var query = new List<ApplicationFormViewModel>();

                foreach (var type in typeSet)
                {
                    var dbSet = Context.Set(type) as IQueryable<ApplicationForm>;

                    var set = dbSet
                        .Where(d => d.CreatorId == CurrentUser.UserId)
                        .Select(t => new ApplicationFormViewModel
                        {
                            Id = t.Id,
                            Creator = t.Creator,
                            ModificationDate = t.ModificationDate,
                            Status = t.Status,
                            ApplicationType = type.Name,
                        });

                    query.AddRange(set);
                }

                return Json(query.OrderByDescending(s => s.ModificationDate).ToDataSourceResult(request));
            }
            else
            {
                var type = Assembly.Load("OA.Models").GetType("OA.Models." + typeName);
                var query = Context.Set(type).AsQueryable();
                return Json(query.ToDataSourceResult(request));
            }

            // 用于性能比较
            //var dbSet = Context.Set(type);
            //foreach (var i in dbSet)
            //{
            //    var t = i as ApplicationForm;

            //    query.Add(new ApplicationFormViewModel
            //    {
            //        Id = t.Id,
            //        Creator = t.Creator,
            //        ModificationDate = t.ModificationDate,
            //        Status = t.Status,
            //        ApplicationType = type.Name,
            //    });
            //}
        }
        /// <summary>
        ///  保存表单
        ///  如果没有表单Id, 则视为新增申请
        ///  如果有表单Id, 则视为编辑
        /// </summary>
        /// <param name="ApplicationType">表单类型</param>
        /// <param name="Id">表单编号</param>
        /// <returns></returns>
        [HttpPost]
        public JsonResult Save(string ApplicationType, string Id)
        {
            var className = "OA.Models." + ApplicationType;
            var typeName = Assembly.Load("OA.Models").GetType(className);
            var isNew = string.IsNullOrWhiteSpace(Id);

            if (isNew)
            {
                dynamic entity = typeName.Assembly.CreateInstance(className);
                entity.CreatorId = CurrentUser.UserId;
                entity.Creator = CurrentUser.Name;

                if (TryUpdateModel(entity))
                {
                    entity.Id = DateTime.Now.ToString("yyyyMMddHHmmss_fffff");
                    entity.ModificationDate = DateTime.Now;
                    entity.Status = ApplicationFormState.未提交;

                    Context.Entry(entity).State = EntityState.Added;
                    Context.SaveChanges();
                    return Json(Success("保存成功"));
                }
            }
            else
            {
                dynamic entity = typeName.Assembly.CreateInstance(className);
                entity.CreatorId = CurrentUser.UserId;
                entity.Creator = CurrentUser.Name;

                if (TryUpdateModel(entity))
                {
                    entity.ModificationDate = DateTime.Now;

                    Context.Entry(entity).State = EntityState.Modified;
                    Context.SaveChanges();
                    return Json(Success("保存成功"));
                }
            }

            var errorMessage = ModelState.Values
                .FirstOrDefault(d => d.Errors.Any())
                ?.Errors[0]
                ?.ErrorMessage;

            return Json(Failed("保存失败:" + errorMessage));
        }
        /// <summary>
        ///  申请表单
        ///  先保存表单, 再进行提交
        /// </summary>
        /// <param name="ApplicationFormType">表单类型</param>
        /// <param name="Id">表单Id</param>
        /// <param name="nextId">下一节点接收人Id</param>
        /// <returns></returns>
        [HttpPost]
        public JsonResult Apply(string ApplicationType, string Id, string nextId)
        {
            var className = "OA.Models." + ApplicationType;
            var typeName = Assembly.Load("OA.Models").GetType(className);
            var isNew = string.IsNullOrWhiteSpace(Id);

            if (isNew)
            {
                dynamic entity = typeName.Assembly.CreateInstance(className);
                entity.CreatorId = CurrentUser.UserId;
                entity.Creator = CurrentUser.Name;

                if (TryUpdateModel(entity))
                {
                    entity.Id = DateTime.Now.ToString("yyyyMMddHHmmss_fffff");
                    entity.ModificationDate = DateTime.Now;
                    entity.Status = ApplicationFormState.申请中;

                    Context.Entry(entity).State = EntityState.Added;
                    Context.SaveChanges();
                    return Json(Success("保存成功"));
                }
            }
            else
            {
                dynamic entity = typeName.Assembly.CreateInstance(className);

                if (TryUpdateModel(entity))
                {
                    entity.Status = ApplicationFormState.申请中;

                    Context.Entry(entity).State = EntityState.Modified;
                    Context.SaveChanges();
                    return Json(Success("保存成功"));
                }
            }



            var errorMessage = ModelState.Values
                .FirstOrDefault(d => d.Errors.Any())
                ?.Errors[0]
                ?.ErrorMessage;

            return Json(Failed("提交失败:" + errorMessage));
        }
    }
}

